کلمات کليدي true و false نيز مي توانند به عنوان unary operators به منظور overload کردن مورد استفاده قرار گيرند. نسخه ي overload شده ي اين operator ها با توجه به کلاسي که شما مي سازيد، شخصي سازي مي شود. هنگامي که true و false براي يک کلاس overload مي شوند، مي توانيد از اشياي آن کلاس براي کنترل کردن if، for، while و do-while و همچنين ? استفاده کنيد.
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
public static bool operator true(TwoD op)
{
retu (op.X != 0 || op.Y != 0);
}
public static bool operator false(TwoD op)
{
retu (op.X == 0 && op.Y == 0);
}
public static TwoD operator --(TwoD op)
{
TwoD result = new TwoD();
result.X = op.X - 1;
result.Y = op.Y - 1;
retu result;
}
public static TwoD operator ++(TwoD op)
{
TwoD result = new TwoD();
result.X = op.X + 1;
result.Y = op.Y + 1;
retu result;
}
public void Show()
{
Console.WriteLine("{0}, {1}", X, Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD ob = new TwoD(5, 5);
if (ob)
Console.WriteLine("ob is true");
Console.WriteLine();
for (; ob; ob--)
{
ob.Show();
}
Console.WriteLine();
ob = new TwoD(-3, -3);
while (ob)
{
ob.Show();
ob++;
}
}
}
دقت کنيد که چگونه از شيء TwoD براي کنترل if و while و for استفاده شده است. به عنوان مثال، در مورد if، شيء TwoD توسط true ارزيابي مي شود. اگر حداقل يکي از فيلدهاي اين شيء مخالف صفر باشد، دستور if اجرا خواهد شد. در مورد حلقه ها، حلقه تا زماني اجرا مي شود که شيء true باشد (فيلدهاي شيء مخالف صفر باشد) و به محض اين که شيء false شد (همه ي فيلدها صفر شدند) برنامه از حلقه خارج مي شود.
overload کردن عملگرهاي منطقي
همان طور که مي دانيد، سي شارپ شامل عملگرهاي منطقي & ، | ، ! و && و || است. البته فقط & و | و ! مي توانند overload شوند. با اين حال با دنبال کردن يک سري قوانين مي توانيد از مزيت هاي && و || بهره ببريد.
اگر قصد استفاده از عملگرهاي منطقي short-circuit را نداشته باشيد، مي توانيد بسيار ساده & و | را overload کنيد که هر کدام از آن ها يک مقدار bool را retu مي کند. overload کردن ! نيز مقدار bool را retu مي کند.
مثال زير عملگرهاي منطقي ! و & و | را overload مي کند. مانند قبل فرض بر اين است که شيء TwoD در صورتي true است که حداقل يکي از فيلدهاي آن غير صفر باشد و در صورتي که همه ي فيلدهاي TwoD صفر باشند، شيء false است:
using System;
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
public static bool operator &(TwoD op1, TwoD op2)
{
retu ((op1.X != 0 && op1.Y != 0) && (op2.X != 0 && op2.Y != 0));
}
public static bool operator |(TwoD op1, TwoD op2)
{
retu ((op1.X != 0 || op1.Y != 0) || (op2.X != 0 || op2.Y != 0));
}
public static bool operator !(TwoD op)
{
retu (op.X == 0 & op.Y == 0);
}
public void Show()
{
Console.WriteLine("{0}, {1}", X, Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD a = new TwoD(1, 2);
TwoD b = new TwoD(8, 8);
TwoD c = new TwoD();
Console.Write("Here is a: ");
a.Show();
Console.Write("Here is b: ");
b.Show();
Console.Write("Here is c: ");
c.Show();
Console.WriteLine();
if(!a)
Console.WriteLine("a is false");
if(!b)
Console.WriteLine("b is false");
if(!c)
Console.WriteLine("c is false");
Console.WriteLine();
if (a & b)
Console.WriteLine("a & b is true");
else
Console.WriteLine("a & b is false");
if(a & c)
Console.WriteLine("a & c is true");
else
Console.WriteLine("a & c is false");
Console.WriteLine();
if(a | b)
Console.WriteLine("a | b is true");
else
Console.WriteLine("a | b i false");
if(a | c)
Console.WriteLine("a | c is true");
else
Console.WriteLine("a | c is false");
}
}
خروجي:
در اين روش، operator method هاي & و | و ! هرکدام يک مقدار bool را retu مي کنند. به دليل اين که از اين operator ها در حالت استاندارد خودشان استفاده شود، retu کردن مقدار bool ضروري است. روشي که در مثال قبل مشاهده کرديد، فقط براي زماني است که به short-circuit نياز نداريد.
فعال کردن operator هاي short-circuit
براي فعال کردن && و || بايد از چهار قاعده پيروي کنيد. يک، کلاس مورد نظر بايد & و | را overload کند. دو، retu type متدهاي overload شده ي & و | بايد از نوع همان کلاسي باشد که اين operator ها در آن overload مي شوند. سه، هر پارامتر بايد به يک شيء از جنس همان کلاسي که operator در آن overload شده است، رجوع کند. چهار، operator هاي true و false بايد براي کلاس مربوطه overload شود.
public TwoD(int a, int b)
{
X = a;
Y = b;
}
// Overload & for short-circuit evaluation.
public static TwoD operator &(TwoD op1, TwoD op2)
{
if ((op1.X != 0 && op1.Y != 0) && (op2.X != 0 && op2.Y != 0))
retu new TwoD(1, 1);
else
retu new TwoD();
}
// Overload | for short-circuit evaluation.
public static TwoD operator |(TwoD op1, TwoD op2)
{
if ((op1.X != 0 || op1.Y != 0) || (op2.X != 0 || op2.Y != 0))
retu new TwoD(1, 1);
else
retu new TwoD();
}
// Overload true.
public static bool operator true(TwoD op)
{
retu (op.X != 0 || op.Y != 0); // at least one field is non-zero
}
// Overload false.
public static bool operator false(TwoD op)
{
retu (op.X == 0 & op.Y == 0); // all fields are zero
}
// Overload !.
public static bool operator !(TwoD op)
{
retu (op.X == 0 & op.Y == 0);
}
public void Show()
{
Console.WriteLine("{0}, {1}", X, Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD a = new TwoD(5, 6);
TwoD b = new TwoD(10, 10);
TwoD c = new TwoD();
Console.Write("Here is a: ");
a.Show();
Console.Write("Here is b: ");
b.Show();
Console.Write("Here is c: ");
c.Show();
Console.WriteLine();
if (!a)
Console.WriteLine("a is false");
if (!b)
Console.WriteLine("b is false");
if (!c)
Console.WriteLine("c is false");
Console.WriteLine();
if (a & b)
Console.WriteLine("a & b is true");
else
Console.WriteLine("a & b is false");
if (a & c)
Console.WriteLine("a & c is true");
else
Console.WriteLine("a & c is false");
Console.WriteLine();
if (a | b)
Console.WriteLine("a | b is true");
else
Console.WriteLine("a | b i false");
if (a | c)
Console.WriteLine("a | c is true");
else
Console.WriteLine("a | c is false");
Console.WriteLine();
// Now use short-circuit ops.
Console.WriteLine("Use short-circuit && and ||");
if (a && b)
Console.WriteLine("a && b is true.");
else
Console.WriteLine("a && b is false.");
if (a && c)
Console.WriteLine("a && c is true.");
else
Console.WriteLine("a && c is false.");
if (a || b)
Console.WriteLine("a || b is true.");
else
Console.WriteLine("a || b is false.");
if (a || c)
Console.WriteLine("a || c is true.");
else
Console.WriteLine("a || c is false.");
}
}
خروجي:
در اين جا نگاهي دقيق تر به برنامه ي بالا مي اندازيم و مي بينيم که چطور & و | اجرا شده اند. به اين قسمت از کد بالا توجه کنيد:
// Overload & for short-circuit evaluation.
public static TwoD operator &(TwoD op1, TwoD op2)
{
if ((op1.X != 0 && op1.Y != 0) && (op2.X != 0 && op2.Y != 0))
retu new TwoD(1, 1);
else
retu new TwoD();
}
// Overload | for short-circuit evaluation.
public static TwoD operator |(TwoD op1, TwoD op2)
{
if ((op1.X != 0 || op1.Y != 0) || (op2.X != 0 || op2.Y != 0))
retu new TwoD(1, 1);
else
retu new TwoD();
}
دقت کنيد که هر دو يک شيء از جنس TwoD را retu مي کنند. توجه داشته باشيد که چگونه اين شيء به وجود آمده است. اگر خروجي عملياتي که انجام شده true باشد، بنابراين يک شيء TwoD که true است (شيء اي که حداقل يکي از فيلدهاي آن غير صفر است) retu مي شود. اگر خروجي false باشد، يک شيء false ساخته شده و سپس retu مي شود.
بنابراين در عباراتي به شکل زير:
1
2
3
4
if (a & b)
Console.WriteLine("a & b is true");
else
Console.WriteLine("a & b is false");
خروجي a & b يک شيء TwoD است که در اين مورد يک شيء true است. از آن جا که operator هاي true و false در اين کلاس تعريف شده اند، شيء اي که retu شده است مربوط به true operator بوده و در نهايت يک مقدار بولين retu مي شود که در اين جا اين شيء true است و در نتيجه مقدار true نيز retu مي شود و محتويات دستور if اجرا خواهد شد.
به دليل اين که قوانين مورد نياز رعايت شده اند، operator هاي short-circuit براي استفاده از اشياي TwoD نيز فعال هستند و به اين صورت کار مي کند که، اولين operand توسط operator true (براي ||) يا operator false (براي &&) بررسي مي شود. اگر خروجي عمليات قابل تشخيص باشد، بنابراين & يا | مربوطه مورد ارزيابي قرار نمي گيرد. در غير اين صورت، از & يا | مربوطه براي يافتن خروجي استفاده مي شود. بنابراين، استفاده از && يا || موجب مي شود & يا | مربوطه تنها زماني فراخواني شود که operand اول نتواند خروجي را مشخص کند. براي نمونه، به کد زير توجه کنيد:
1
if (a || c) Console.WriteLine("a || c is true.");
در ابتدا true operator روي a اعمال مي شود و از آن جا که در اين مورد a برابر با true است، ديگر نيازي به استفاده از | operator نيست. اما در کد زير:
if (c || a) Console.WriteLine(“a || c is true.”);
ابتدا true operator روي c اعمال مي شود که در اين مورد c برابر با false است. بنابراين، | operator فراخواني خواهد شد تا بررسي شود که آيا a برابر با true است يا خير (که در اين مورد، a برابر با true است). شايد در ابتدا فکر کنيد که تکنيک استفاده شده براي فعال کردن short-circuit مقداري پيچيده و دشوار باشد اما اگر اندکي در مورد آن فکر کنيد متوجه خواهيد شد که کارهاي انجام شده منطقي به نظر مي رسد. در حالت کلي، بهتر است از همين روش استفاده کنيد.
Conversion Operators
در برخي از مواقع، مي خواهيد از شيء يک کلاس در عبارتي استفاده کنيد که شامل data type هاي ديگري نيز است. در بعضي موارد، overload کردن يک يا چند operator مي تواند اين کار را براي شما انجام دهد اما گاهي چيزي که شما نياز داريد يک تبديل ساده از نوع کلاس به نوع مورد نظرتان است. براي انجام اين دسته از موارد، سي شارپ به شما اجازه مي دهد نوع خاصي از operator method را بسازيد که conversion operator ناميده مي شود. Conversion operator يک شيء از کلاس شما را به نوع ديگري که مد نظرتان است تبديل مي کند.
دو حالت از conversion operator موجود است: implicit و explicit که فرم کلي آن ها به شکل زير است:
public static operator implicit target-type(source-type v) { retu value; }
public static operator explicit target-type(source-type v) { retu value; }
در اين جا، target-type مشخص کننده ي نوعي است که قصد داريد source-type را به آن تبديل کنيد و value مقدار کلاس، بعد از تبديل است. Conversion operator اطلاعات را مطابق با target-type باز مي گرداند (retu مي کند).
اگر conversion operator به طور implicit مشخص شود، بنابراين conversion به صورت اتوماتيک انجام خواهد شد، مثل حالتي که شيء در يک عبارت همراه با يک data type ديگري از نوع target-type در تعامل است. هنگامي که conversion به صورت explicit تعريف شده باشد، بنابراين هنگامي که cast مورد نياز است conversion فراخواني مي شود. توجه کنيد که نمي توانيد براي يک source-type و target-type هم implicit و explicit را تعريف کنيد.
براي نشان دادن conversion operator آن را در کلاس TwoD اعمال مي کنيم. با فرض اينکه مي خواهيد يک شيء TwoD را به يک int تبديل کنيد و در يک عبارت از جنس int از آن استفاده نماييد:
public TwoD(int a, int b)
{
X = a;
Y = b;
}
public static implicit operator int(TwoD op)
{
retu op.X * op.Y;
}
}
class OpOvDemo
{
static void Main()
{
TwoD ob1 = new TwoD(2, 2);
TwoD ob2 = new TwoD(1, 1);
int i = ob1 * 3;
Console.WriteLine(i);
i = ob1 - 3;
Console.WriteLine(i);
i = ob1 + ob2;
Console.WriteLine(i);
i = ob1;
Console.WriteLine(i);
}
}
برچسب: طراحی وب سایت, طراحی سایت, طراحی وب,
نویسنده: pooyesh
تاريخ: چهارشنبه
16 مرداد
1392 ساعت: 15:41